package com.junjie.checkin.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.junjie.checkin.entity.Enum.ActivityHistoryStatusEnum;
import com.junjie.checkin.entity.Enum.ActivityStatusEnum;
import com.junjie.checkin.entity.TActivity;
import com.junjie.checkin.entity.TStudentActivityHistory;
import com.junjie.checkin.exception.InvalidTimeRangeException;
import com.junjie.checkin.exception.ResourceNotFountException;
import com.junjie.checkin.exception.signUp.ModificationException;
import com.junjie.checkin.mapper.StudentActivityHistoryMapper;
import com.junjie.checkin.request.activity.ActivityPageRequest;
import com.junjie.checkin.mapper.ActivityMapper;
import com.junjie.checkin.request.activity.ActivityParticipationRequest;
import com.junjie.checkin.request.activity.ActivityRequest;
import com.junjie.checkin.request.activity.RegistrationListPageRequest;
import com.junjie.checkin.response.admin.*;
import com.junjie.checkin.response.PageResult;
import com.junjie.checkin.security.service.impl.JwtServiceImpl;
import com.junjie.checkin.utils.DateTimeFormat;
import com.junjie.checkin.websocket.entity.StompMessage;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.io.InputStream;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


@Service
public class AdminActivityService {
    @Autowired
    private ActivityMapper activityMapper;
    @Autowired
    private StudentActivityHistoryMapper activityHistoryMapper;
    @Autowired
    private JwtServiceImpl jwtService;
    @Autowired
    private SimpMessagingTemplate simpMessagingTemplate;

    /**
     * 获取活动列表
     * @param activityPageRequest 查询参数
     * @return 分页结果
     */
    public PageResult<ActivityResponse> getActivities(ActivityPageRequest activityPageRequest) {
        PageHelper.startPage(activityPageRequest.getPage(), activityPageRequest.getPageSize());
        Page<ActivityResponse> page = activityMapper.pageQueryWithParticipantCount(activityPageRequest);
        return new PageResult<>(page.getTotal(), page.getResult());
    }

    /**
     * 获取活动详情 (已完成修改)
     * @param id 活动id
     * @return 活动详细数据
     */
    public ActivityDetailsResponse getActivityById(Integer id) {
        TActivity activity = activityMapper.selectById(id);
        // 检查活动是否存在
        if (activity == null){
            throw new ResourceNotFountException();
        }
        ActivityDetailsResponse detailsResponse = new ActivityDetailsResponse();
        // 转换对象
        BeanUtils.copyProperties(activity,detailsResponse);
        // 格式化日期
        detailsResponse.setStartTime(DateTimeFormat.dateToString(activity.getStartTime()));
        detailsResponse.setEndTime(DateTimeFormat.dateToString(activity.getEndTime()));
        detailsResponse.setCreateTime(DateTimeFormat.dateToString(activity.getCreateTime()));
        detailsResponse.setUpdateTime(DateTimeFormat.dateToString(activity.getUpdateTime()));
        // 获取参与人数
        Integer activityParticipants = activityHistoryMapper.getActivityParticipants(activity.getId());
        detailsResponse.setCurrentParticipants(activityParticipants);

        return detailsResponse;
    }

    /**
     * 添加活动 (已完成)
     * @param activityRequest 添加活动信息
     * @param token 用户令牌,用来获取创建者身份
     * @return 添加的活动信息
     */
    public ActivityResponse addActivity(ActivityRequest activityRequest,String token) throws ParseException {
        TActivity activity = new TActivity();
        BeanUtils.copyProperties(activityRequest,activity);
        // 对时间进行校验
        String startTime = activityRequest.getStartTime();
        String endTime = activityRequest.getEndTime();
        this.checkTimeRange(startTime,endTime);
        // 修改时间格式
        activity.setStartTime(DateTimeFormat.stringToDate(startTime));
        activity.setEndTime(DateTimeFormat.stringToDate(endTime));

        // 添加创建者和修改者
        activity.setCreateBy(jwtService.getUserName(token));
        activity.setUpdateBy(jwtService.getUserName(token));
        activityMapper.insert(activity);
        // 响应数据封装
        ActivityResponse activityResponse = new ActivityResponse();
        BeanUtils.copyProperties(activity,activityResponse);

        // 格式化日期字符串
        activityResponse.setStartTime(DateTimeFormat.dateToString(activity.getStartTime()));
        activityResponse.setEndTime(DateTimeFormat.dateToString(activity.getEndTime()));
        activityResponse.setCurrentParticipants(0);
        // 发送STOMP消息
        if (activity.getStatus().equals(ActivityStatusEnum.PUBLISHED)){
            // 封装STOMP消息
            StompMessage<ActivityResponse> stompMessage = new StompMessage<>("activity","活动发布",activityResponse);
            simpMessagingTemplate.convertAndSend("/topic/activity",activity);
        }
        return activityResponse;
    }

    /**
     * 更新活动 (已完成)
     * @param id 活动ID
     * @param activityRequest  更新的数据
     * @param token 当前用户的token
     * @throws ParseException 解析异常
     */
    public void updateActivity(int id ,ActivityRequest activityRequest,String token) throws ParseException {
        // 根据 id 查询现有活动信息
        TActivity existingActivity = activityMapper.selectById(id);
        if (existingActivity == null) {
            throw new ResourceNotFountException();
        }
        String startTime = activityRequest.getStartTime();
        String endTime = activityRequest.getEndTime();

        // 检查活动时间范围
        this.checkTimeRange(startTime,endTime);

        // 将 ActivityRequest 中的值复制到现有活动对象中
        BeanUtils.copyProperties(activityRequest, existingActivity);

        // 更新修改者
        String userName = jwtService.getUserName(token);
        existingActivity.setUpdateBy(userName);

        // 特殊字段处理（如时间格式转换）
        try {
            existingActivity.setStartTime(DateTimeFormat.stringToDate(activityRequest.getStartTime()));
            existingActivity.setEndTime(DateTimeFormat.stringToDate(activityRequest.getEndTime()));
        } catch (ParseException e) {
            throw new IllegalArgumentException("时间格式错误", e);
        }
        // 更新数据库记录
        activityMapper.updateById(existingActivity);
    }


    /**
     * 取消活动
     * @param id 要取消的id
     */
    public void cancelActivity(Integer id){
        // 检查资源是否存在
        TActivity existingActivity = activityMapper.selectById(id);
        if (existingActivity == null){
            throw new ResourceNotFountException();
        }
        activityMapper.updateStatus(id,"cancelled");
    }

    /**
     * 检查时间范围
     * @param startTime 开始时间
     * @param endTime 结束时间
     * @throws ParseException 时间格式错误
     */
    private void checkTimeRange(String startTime, String endTime) throws ParseException {
        Date start = DateTimeFormat.stringToDate(startTime);
        Date end = DateTimeFormat.stringToDate(endTime);
        // 如果开始时间晚于结束时间,则抛出异常
        if (start.after(end)){
            throw new InvalidTimeRangeException();
        }
    }

    /**
     * 获取最新活动
     * @param limit
     * @return
     */
    public List<RecentActivitiesResponse> getLatestActivities(int limit) {
        return activityMapper.selectLatestActivities(limit);
    }

    /**
     * 获取活动报名详情
     * @param id
     * @return
     */
    public RegistrationDetailsResponse getRegistrationDetails(Integer id) {

        if (id == null ){
            throw new ResourceNotFountException();
        }
        //获取活动报名人数
        Map map = new HashMap();
        map.put("activityId",id);
        Integer registration = activityHistoryMapper.getStatusNumber(map);
        map.put("status",1);
        Integer sign = activityHistoryMapper.getStatusNumber(map);
        map.put("status",2);
        Integer cancel = activityHistoryMapper.getStatusNumber(map);

        return RegistrationDetailsResponse.builder()
                .registration(registration)
                .cancel(cancel)
                .sign(sign)
                .build();
    }

    /**
     * 获取活动报名列表
     * @param request
     * @return
     */
    public PageResult<RegistrationListPageResponse> getRegistrationList(RegistrationListPageRequest request) {
        request.initDefault();
        PageHelper.startPage(request.getPage(), request.getPageSize());
        Page<RegistrationListPageResponse> page = activityMapper.getRegistrationList(request);
        List<RegistrationListPageResponse> modifiedList = page.getResult().stream()
                .peek(item -> {
                    if (item.getStatus() != null) {
                        switch (item.getStatus()) {
                            case SIGN_UP:
                                break;
                            default:
                                item.setUpdateTime(null);
                                // 其他状态不做处理
                                break;
                        }
                    }
                })
                .collect(Collectors.toList());
        return new PageResult<>(page.getTotal(), modifiedList);
    }

    /**
     * 导出报名学生数据报表
     * @param response
     */
    public void exportBusinessData(Integer id, HttpServletResponse response) {
        //获取报名学生列表数据
        List<RegistrationListPageResponse> list = new ArrayList<RegistrationListPageResponse>();
        list = activityHistoryMapper.getRegistrationList(id);
        //获取活动信息
        TActivity activity = activityMapper.selectById(id);
        //2.通过poi将数据写入excel文件中
        InputStream in = this.getClass().getClassLoader().getResourceAsStream("template/报名学生列表模板.xlsx");
        try {
            //创建工作簿
            XSSFWorkbook sheets = new XSSFWorkbook(in);
            //获取第一个表单
            XSSFSheet sheet = sheets.getSheet("Sheet1");
            //设置活动标题
            sheet.getRow(1).getCell(2).setCellValue(activity.getTitle());
            //设置活动描述
            sheet.getRow(2).getCell(2).setCellValue(activity.getDescription());
            //设置活动地点
            sheet.getRow(3).getCell(2).setCellValue(activity.getLocation());
            //设置活动时间
            sheet.getRow(4).getCell(4).setCellValue("活动开始时间："+activity.getStartTime().toString() + "至" + activity.getEndTime().toString());

            //设置学生信息
            for (int i = 0; i < list.size(); i++) {
                XSSFRow row = sheet.getRow(i + 7);
                row.getCell(1).setCellValue(i+1);
                row.getCell(2).setCellValue(list.get(i).getUsername());
                row.getCell(3).setCellValue(list.get(i).getNickname());
                row.getCell(4).setCellValue(list.get(i).getCreateTime());
            }
            //3.通过输出流将excel文件下载到客户端
            ServletOutputStream out = response.getOutputStream();
            sheets.write(out);
            //4.关闭流
            out.close();
            sheets.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 活动参与记录查询
     * @param
     * @return
     */
    public PageResult<ActivityParticipationResponse> getJoinPageActivities(ActivityParticipationRequest request) {
        PageHelper.startPage(request.getPage(), request.getPageSize());
        Page<ActivityParticipationResponse> page = activityMapper.getJoinPageActivities(request);
        return new PageResult<>(page.getTotal(), page.getResult());
    }

    /**
     * 批量签到
     * @param ids
     */
    public void batchCheckIn(List<Long> ids,Long activityId) {
        List<TStudentActivityHistory> byListIds = activityHistoryMapper.getByListIds(ids);
        for (TStudentActivityHistory byListId : byListIds) {
            if(byListId.getStatus() == ActivityHistoryStatusEnum.SIGN_UP){
                throw new ModificationException();
            }
        }
        activityHistoryMapper.batchCheckIn(ids,activityId);
    }

    /**
     * 手动签到
     * @param id
     */
    public void manualCheckIn(Integer id) {
        activityHistoryMapper.updateStatus(id);
    }

    /**
     * 取消报名
     * @param id
     */
    public void cancelRegistration(Integer id) {
        activityHistoryMapper.cancelRegistration(id);
    }
}
